package com.pencilisland.pay.mgt.app.service.impl;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Order;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import com.pencilisland.pay.mgt.app.entity.TenantEntity;
import com.pencilisland.pay.mgt.app.entity.TenantEntity_;
import com.pencilisland.pay.mgt.app.repository.TenantRepository;
import com.pencilisland.pay.mgt.app.service.TenantService;
import com.pencilisland.pay.mgt.console.entity.SysUser;
import com.pencilisland.pay.mgt.console.service.UserService;
import com.pencilisland.pay.mgt.util.RandomUtil;

@Component
public class TenantServiceImpl implements TenantService {
	private static final Long base = 116100L;

	private static final String locker = "LOGIN_NAME_LOCKER";

	private static Long current = null;

	@Autowired
	TenantRepository tenantRepo;
	@Autowired
	UserService userService;

	@Override
	public Page<TenantEntity> tenantList(final TenantEntity cretiria, int start, int limit) {

		Specification<TenantEntity> spec = new Specification<TenantEntity>() {

			@Override
			public Predicate toPredicate(Root<TenantEntity> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
				List<Predicate> list = new ArrayList<Predicate>();
				if (!StringUtils.isEmpty(cretiria.getName())) {
					list.add(cb.like(root.get(TenantEntity_.name), "%" + cretiria.getName() + "%"));
				}
				if (!StringUtils.isEmpty(cretiria.getCode())) {
					list.add(cb.equal(root.get(TenantEntity_.code), cretiria.getCode()));
				}
				Predicate[] p = new Predicate[list.size()];
				return cb.and(list.toArray(p));
			}
		};

		Sort sort = new Sort(new Order(Sort.Direction.DESC, TenantEntity_.createTime.getName()));

		Pageable pageable = new PageRequest(start/limit, limit, sort);

		return tenantRepo.findAll(spec, pageable);

	}

	@Override
	public TenantEntity save(TenantEntity tenant) {
		if (tenant.getId() == null) {
			tenant.setCreateTime(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss")));
			tenant.setStatus(0);
			tenant.setCode(RandomUtil.genOrder("CT", 15));
		} else {
			TenantEntity exit = tenantRepo.findOne(tenant.getId());
			if (exit != null) {
				tenant.setStatus(exit.getStatus());
				tenant.setCreateTime(exit.getCreateTime());
				tenant.setUserId(exit.getUserId());
				tenant.setLoginName(exit.getLoginName());
			}
		}
		return tenantRepo.save(tenant);
	}


	@Override
	public TenantEntity loadData(Long id) {
		return tenantRepo.findOne(id);
	}

	@Override
	public void delete(Long id) {
		tenantRepo.delete(id);
	}

	@Override
	public Long gen() {
		synchronized (locker) {

			if (current == null) {
				String maxLoginName = tenantRepo.findMaxLoginName();
				if (StringUtils.isEmpty(maxLoginName)) {
					current = base;
				} else {
					current = Long.valueOf(maxLoginName) + 1;
				}
			}

			return current++;
		}
	}

	@Override
	public TenantEntity sessionData() {
		SysUser user = userService.findSessionUser();
		return tenantRepo.findByUserId(user.getUserId());
	}

}
